package com.lemon.cloud.security.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Sets;
import com.lemon.cloud.comm.constants.OAuth2Constant;
import com.lemon.cloud.comm.constants.enums.MenuTypeEnum;
import com.lemon.cloud.comm.constants.enums.UserTypeEnum;
import com.lemon.cloud.comm.po.SocialUser;
import com.lemon.cloud.comm.po.SysMenu;
import com.lemon.cloud.comm.po.SysRole;
import com.lemon.cloud.comm.po.SysUser;
import com.lemon.cloud.security.model.SecurityUser;
import org.springframework.core.Ordered;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;

import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public interface SecurityUserService extends UserDetailsService, Ordered {
    /**
     * 是否支持此客户端校验
     *
     * @param clientId 目标客户端
     * @return true/false
     */
    default boolean support(String clientId, String grantType) {
        return true;
    }

    /**
     * 排序值 默认取最大的
     *
     * @return 排序值
     */
    @Override
    default int getOrder() {
        return 0;
    }

    /**
     * 构建 UserDetails 实例
     *
     * @return UserDetails
     */
    default UserDetails getUserDetails(SysUser user,
                                       List<SysRole> roleList) {
        Set<String> authoritiesSet = Sets.newHashSet();
        if (roleList != null) {
            if (CollectionUtil.isNotEmpty(roleList)) {
                List<String> roleCodeList = roleList.stream().map(SysRole::getCode).collect(Collectors.toList());
                authoritiesSet.addAll(roleCodeList);
                roleList.forEach(role -> {
                    if (CollectionUtil.isNotEmpty(role.getPermissionList())) {
                        authoritiesSet.addAll(role.getPermissionList().stream()
                                .filter(m -> MenuTypeEnum.BUTTON.getType().equals(m.getType()))
                                .map(SysMenu::getPermission)
                                .filter(StrUtil::isNotEmpty).collect(Collectors.toList()));
                    }
                });
            }
        }

        //authorities = 角色的code+方法权限code

        Collection<GrantedAuthority> authorities = AuthorityUtils
                .createAuthorityList(authoritiesSet.toArray(new String[0]));
        SecurityUser securityUser = new SecurityUser(user.getUsername(),
                OAuth2Constant.BCRYPT + user.getPassword(), authorities);
        securityUser.setUserTypeEnum(UserTypeEnum.SYS_USER);
        securityUser.setSysUser(user);
        return securityUser;
    }

    default UserDetails getUserDetails(SocialUser socialUser,
                                       List<SysRole> roleList) {
        Set<String> authoritiesSet = Sets.newHashSet();
        if (roleList != null) {
            if (CollectionUtil.isNotEmpty(roleList)) {
                List<String> roleCodeList = roleList.stream().map(SysRole::getCode).collect(Collectors.toList());
                authoritiesSet.addAll(roleCodeList);
                roleList.forEach(role -> {
                    if (CollectionUtil.isNotEmpty(role.getPermissionList())) {
                        authoritiesSet.addAll(role.getPermissionList().stream()
                                .filter(m -> MenuTypeEnum.BUTTON.getType().equals(m.getType()))
                                .map(SysMenu::getPermission)
                                .filter(StrUtil::isNotEmpty).collect(Collectors.toList()));
                    }
                });
            }
        }

        //authorities = 角色的code+方法权限code

        Collection<GrantedAuthority> authorities = AuthorityUtils
                .createAuthorityList(authoritiesSet.toArray(new String[0]));
        SecurityUser securityUser = new SecurityUser(socialUser.getProviderUserId(),
                OAuth2Constant.BCRYPT + socialUser.getState(), authorities);
        securityUser.setUserTypeEnum(UserTypeEnum.SOCIAL_USER);
        securityUser.setSocialUser(socialUser);
        return securityUser;
    }

    /**
     * 通过用户实体查询
     *
     * @param securityUser user
     * @return
     */
    default UserDetails loadUserByUser(SecurityUser securityUser) {
        return this.loadUserByUsername(securityUser.getUsername());
    }

}
